package gl.java.network.transport.kcp.umsp;

import gl.java.network.transport.kcp.core.ChannelOptionHelper;
import gl.java.network.transport.kcp.core.UkcpChannel;
import gl.java.network.transport.kcp.core.UkcpChannelOption;
import gl.java.network.transport.kcp.core.UkcpClientChannel;
import gl.java.umsp.*;
import gl.java.umsp.client.UmspClient;
import gl.java.umsp.client.UmspClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;
import sun.security.jca.GetInstance;

import java.util.Random;

@Slf4j
public class UmspKcpClient {

    private static String HOST = "118.24.53.22";
    private static int PORT = 12343;

    private Bootstrap b;


    private UmspKcpClient() {
        EventLoopGroup group = new NioEventLoopGroup();
        b = new Bootstrap();
        b.group(group).channel(UkcpClientChannel.class);
        ChannelOptionHelper.nodelay(b, true, 20, 2, true)
                .option(UkcpChannelOption.UKCP_MTU, 512);
    }

    public static void main(String[] args) throws Exception {

        UmspKcpClient.connect(HOST, PORT, new UmspClientHandler() {
            @Override
            protected void channelRead0(ChannelHandlerContext ctx, UmspHeader msg) throws Exception {
                log.info("onMessage " + msg + ", from " + ((UkcpChannel) ctx.channel()).channelID());
                super.channelRead0(ctx, msg);

            }

            @Override
            public void channelActive(ChannelHandlerContext ctx) throws InterruptedException {
                super.channelActive(ctx);
                UkcpChannel channel = (UkcpChannel) ctx.channel();
                channel.channelID(100);

            }

            @Override
            public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                super.channelInactive(ctx);
                log.info("onDisConnect:" + ctx);
            }

            @Override
            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                super.exceptionCaught(ctx, cause);
                log.warn("onErr:" + cause);
            }
        });
    }

    private static class Singleton {
        private static UmspKcpClient INSTANCE = new UmspKcpClient();
    }

    public static UmspKcpClient getInstance() {
        return Singleton.INSTANCE;
    }

    public static void connect(String host, int port, final UmspClientHandler handler) {
        UmspKcpClient.getInstance().b.handler(
                new ChannelInitializer<UkcpChannel>() {
                    @Override
                    public void initChannel(UkcpChannel ch) throws Exception {
                        log.warn("init channel");
                        ChannelPipeline p = ch.pipeline().addLast(
//                                new UmspKcpConnectionHandler(),
                                UmspAutoHeartBeatHandler.newHandler(ch.pipeline()),
                                new UmspMessagePacker(),
                                new UmspMessageUnpacker(),
                                new UmspMessageDecoder(),
                                handler
                        );
//                            p.addLast(new KcpRttClientHandler(11));
                    }
                });
        ChannelFuture f = UmspKcpClient.getInstance().b.connect(host, port);
    }
}
